﻿using System;
using System.Data;
using System.Configuration;
using System.Configuration.Provider;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
using System.IO;
using System.Net;
using Newtonsoft.Json.Linq;

namespace OAuth.Code
{
    /// <summary>
    /// Denglu.cc OAuth_2 的摘要说明
    /// 内容：Denglu OAuth 2.0接口类文件
    /// 作者：cyheng
    /// 版本：v1.1
    /// 日 期：2012-09-23
    /// </summary>
    public class Denglu : mscook.mvc.Core.IDenglu
    {
        /// <summary>
        /// denglu API的域名，默认http://open.denglu.cc
        /// 设置此属性以满足以后有做二级域名重定向需求的客户
        /// </summary>
        public static String domain = "http://open.denglu.cc";

        /// <summary>
        /// DENGLU RESTful API的地址
        /// </summary>
        protected static readonly Dictionary<string, string> apiPath = new Dictionary<string, string> {
            { "user_info",  Denglu.domain + "/api/v4/user_info" },
            { "get_media",  Denglu.domain + "/api/v4/get_media" },
            { "bind",       Denglu.domain + "/api/v4/bind" },
            { "unbind",     Denglu.domain + "/api/v4/unbind" },
            { "all_unbind", Denglu.domain + "/api/v4/all_unbind" },
            { "send_login_feed",    Denglu.domain + "/api/v4/send_login_feed" },
            { "share",      Denglu.domain + "/api/v4/share" }
        };

        private String appID;
        protected String AppID
        {
            get { return appID; }
            set { appID = value; }
        }
        private String apiKey;
        protected String ApiKey
        {
            get { return apiKey; }
            set { apiKey = value; }
        }
        private String signatureMethod;
        protected String SignatureMethod
        {
            get { return signatureMethod; }
            set { signatureMethod = value; }
        }

        /// <summary>
        /// Provider的枚举，里面包括了/transfer/[name]的地址后缀
        /// </summary>
        public static readonly Dictionary<string, Provider> providers = new Dictionary<string, Provider>
        { { "Google", new Provider(Denglu.domain + "/transfer/google", Denglu.domain + "/transfer/google", 1, "Google") },
            { "WindowsLive", new Provider(Denglu.domain + "/transfer/windowslive", Denglu.domain + "/transfer/windowslive", 2, "Windows Live") },
            { "Sina", new Provider(Denglu.domain + "/transfer/sina", Denglu.domain + "/transfer/sina", 3, "新浪微博") },
            { "Tencent", new Provider(Denglu.domain + "/transfer/tencent", Denglu.domain + "/transfer/tencent", 4, "腾讯微博") },
            { "Sohu", new Provider(Denglu.domain + "/transfer/sohu", Denglu.domain + "/transfer/sohu", 5, "搜狐微博") },
            { "Netease", new Provider(Denglu.domain + "/transfer/netease", Denglu.domain + "/transfer/netease", 6, "网易微博") },
            { "Renren", new Provider(Denglu.domain + "/transfer/renren", Denglu.domain + "/transfer/renren", 7, "人人网") },
            { "Kaixin001", new Provider(Denglu.domain + "/transfer/kaixin001", Denglu.domain + "/transfer/kaixin001", 8, "开心网") },
            { "Douban", new Provider(Denglu.domain + "/transfer/douban", Denglu.domain + "/transfer/douban", 9, "豆瓣网") },
            { "Yahoo", new Provider(Denglu.domain + "/transfer/yahoo", Denglu.domain + "/transfer/yahoo", 12, "雅虎") },
            { "QZone", new Provider(Denglu.domain + "/transfer/qzone", Denglu.domain + "/transfer/qzone", 13, "QQ空间") },
            { "Taobao", new Provider(Denglu.domain + "/transfer/taobao", Denglu.domain + "/transfer/taobao", 16, "淘宝") },
            { "Tianya", new Provider(Denglu.domain + "/transfer/tianya", Denglu.domain + "/transfer/tianya", 17, "天涯") },
            { "AlipayQuick", new Provider(Denglu.domain + "/transfer/alipayquick", Denglu.domain + "/transfer/alipayquick", 18, "支付宝") },
            { "Baidu", new Provider(Denglu.domain + "/transfer/baidu", Denglu.domain + "/transfer/baidu", 19, "百度")}
        };

        /// <summary>
        /// HTTP Methods
        /// </summary>
        public enum Verb
        {
            GET, POST, PUT, DELETE
        }

        /// <summary>
        /// 此sdk的版本号，初始为1.0
        /// </summary>
        public static readonly float version = 1.0F;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="appID">灯鹭后台分配的appID {@link http://open.denglu.cc}</param>
        /// <param name="apiKey">灯鹭后台分配的apiKey {@link http://open.denglu.cc}</param>
        /// <param name="signatureMethod">签名算法，暂时只支持MD5</param>
        public Denglu(String appID, String apiKey, String signatureMethod)
        {
            this.AppID = appID;
            this.ApiKey = apiKey;
            this.SignatureMethod = signatureMethod;
        }

        /// <summary>
        /// 获取登录/绑定的链接
        /// </summary>
        /// <param name="isBind">是否用于绑定（非绑定则为登录）</param>
        /// <param name="Provider">供应商的种类，在provider枚举中获得</param>
        /// <param name="uid">用户网站的用户ID，绑定时需要</param>
        public String getAuthUrl(bool isBind, String provider, String uid)
        {
            Provider p = Denglu.providers[provider];
            if (isBind && null == uid)
            {
                throw new DengluException(1, "绑定时，需要传送用户ID");
            }
            return !isBind ? p.AuthUrl + "?appid=" + appID : p.BindUrl + "?appid=" + appID + "&uid=" + uid;
        }

        public string getUserInfoByToken_(String token)
        {
            String url = Denglu.apiPath["user_info"];
            List<Parameter> parameters = new List<Parameter>();
            parameters.Add(new Parameter("appid", this.appID));
            parameters.Add(new Parameter("token", token));
            parameters.Add(new Parameter("timestamp", ((DateTime.UtcNow.Ticks - DateTime.Parse("01/01/1970 00:00:00").Ticks) / 10000).ToString()));
            parameters.Add(new Parameter("sign_type", SignatureMethod));
            parameters = this.signRequest(parameters);

            string times = ((DateTime.UtcNow.Ticks - DateTime.Parse("01/01/1970 00:00:00").Ticks) / 10000).ToString();

            String param_s = "appid=" + this.AppID + "sign_type=" + SignatureMethod + "timestamp=" + times + "token=" + token + "version=" + version.ToString();

            String sign = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(param_s + this.ApiKey, "MD5").ToLower();

            String param = "appid=" + this.AppID + "&sign_type=" + SignatureMethod + "&timestamp=" + times + "&token=" + token + "&version=" + version.ToString() + "&sign=" + sign;

            return url + "?" + param;

            //url += "?";
            //foreach (var item in parameters)
            //{
            //    if (!url.EndsWith("?"))
            //    {
            //        url += "&";
            //    }
            //    url += item.toParamString();
            //}
            //return url;

            //HttpWebRequest request = this.combineRequest(url, parameters);

            //String result = this.makeRequest(request);
            //return (JObject)this.parseJson(result);
        }

        /// <summary>
        /// 根据token获取用户信息
        /// 返回值示例
        /// {
        /// 	"mediaID":7, // 媒体ID
        /// 	"createTime":"2011-05-20 16:44:19", // 创建时间
        /// 	"friendsCount":0, // 好友数
        /// 	"location":null, // 地址
        /// 	"favouritesCount":0, // 收藏数
        /// 	"screenName":"denglu", // 显示姓名
        /// 	"profileImageUrl":"http://head.xiaonei.com/photos/0/0/men_main.gif", // 个人头像
        /// 	"mediaUserID":61, // 用户ID
        /// 	"url":null, // 用户博客/主页地址
        /// 	"city":null, // 城市
        /// 	"description":null, // 个人描述
        /// 	"createdAt":"", // 在媒体上的创建时间
        /// 	"verified":0, // 认证标志
        /// 	"name":null, // 友好显示名称
        /// 	"domain":null, // 用户个性化URL
        /// 	"province":null, // 省份
        /// 	"followersCount":0, // 粉丝数
        /// 	"gender":1, // 性别 1--男，0--女,2--未知
        /// 	"statusesCount":0, // 微博/日记数
        /// 	"personID":120 // 个人ID
        /// }
        /// </summary>
        /// <param name="token">从灯鹭获得的临时token</param>
        public JObject getUserInfoByToken(String token)
        {
            String url = Denglu.apiPath["user_info"];
            List<Parameter> parameters = new List<Parameter>();
            parameters.Add(new Parameter("appid", this.AppID));
            parameters.Add(new Parameter("sign_type", this.signatureMethod));
            parameters.Add(new Parameter("timestamp", ((DateTime.UtcNow.Ticks - DateTime.Parse("01/01/1970 00:00:00").Ticks) / 10000).ToString()));
            parameters.Add(new Parameter("token", token));
            parameters.Add(new Parameter("version", Denglu.version.ToString()));

            parameters = this.signRequest(parameters);

            HttpWebRequest request = this.combineRequest(url, parameters);

            String result = this.makeRequest(request);
            return (JObject)this.parseJson(result);
        }

        /// <summary>
        /// 获取当前应用ID绑定的所有社会化媒体及其属性
        /// 返回值示例
        /// [
        /// 	{
        /// 		"mediaID":7, // ID
        /// 		"mediaIconImageGif": "http://test.denglu.cc/images/denglu_second_icon_7.gif",
        /// //社会化媒体亮色Icon
        /// 		"mediaIconImage": "http://test.denglu.cc/images/denglu_second_icon_7.png", //
        /// 社会化媒体亮色Icon
        /// 		"mediaNameEn":"renren", // 社会化媒体的名称的拼音
        /// 		"mediaIconNoImageGif" :"http://test.denglu.cc/images/denglu_second_icon_no_7.
        /// gif", // 社会化媒体灰色Icon
        /// 		"mediaIconNoImage": "http://test.denglu.cc/images/denglu_second_icon_no_7.
        /// png", // 社会化媒体灰色Icon
        /// 		"mediaName":"人人网", // 社会化媒体的名称
        /// 		"mediaImage":"http://test.denglu.cc/images/denglu_second_7.png" , //
        /// 社会化媒体大图标
        /// 		"shareFlag":0, // 是否有分享功能 0是1否
        /// 		"apiKey":"704779c3dd474a44b612199e438ba8e2" // 社会化媒体的应用apikey
        /// 	}
        /// ]
        /// </summary>
        public JArray getMedia()
        {
            String url = Denglu.apiPath["get_media"];
            List<Parameter> parameters = new List<Parameter>();
            parameters.Add(new Parameter("appid", this.appID));
            parameters = this.signRequest(parameters);

            HttpWebRequest request = this.combineRequest(url, parameters);

            String result = this.makeRequest(request);
            return (JArray)this.parseJson(result);
        }

        /// <summary>
        /// 用户绑定多个社会化媒体账号到已有账号上
        /// 返回值示例
        /// {"result": "1"}
        /// </summary>
        /// <param name="mediaUID">从灯鹭获取的mediaUserID</param>
        /// <param name="uid">用户网站那边的用户ID</param>
        /// <param name="uname">用户网站的昵称</param>
        /// <param name="uemail">用户网站的邮箱</param>
        public JObject bind(String mediaUID, String uid, String uname, String uemail)
        {
            String url = Denglu.apiPath["bind"];
            List<Parameter> parameters = new List<Parameter>();
            parameters.Add(new Parameter("appid", this.appID));
            parameters.Add(new Parameter("muid", mediaUID));
            parameters.Add(new Parameter("uid", uid));
            parameters.Add(new Parameter("uname", uname));
            parameters.Add(new Parameter("uemail", uemail));
            parameters = this.signRequest(parameters);

            HttpWebRequest request = this.combineRequest(url, parameters);

            String result = this.makeRequest(request);
            return (JObject)this.parseJson(result);
        }

        /// <summary>
        /// 用户解除绑定社会化媒体账号
        /// </summary>
        /// <param name="mediaUID">从灯鹭获取的mediaUserID</param>
        public JObject unbind(String mediaUID)
        {
            String url = Denglu.apiPath["unbind"];
            List<Parameter> parameters = new List<Parameter>();
            parameters.Add(new Parameter("appid", this.appID));
            parameters.Add(new Parameter("muid", mediaUID));
            parameters = this.signRequest(parameters);

            HttpWebRequest request = this.combineRequest(url, parameters);

            String result = this.makeRequest(request);
            return (JObject)this.parseJson(result);
        }

        /// <summary>
        /// 发送登录的新鲜事
        /// </summary>
        /// <param name="mediaUID">从灯鹭获取的mediaUserID</param>
        public void sendLoginFeed(String mediaUID)
        {
            String url = Denglu.apiPath["send_login_feed"];
            List<Parameter> parameters = new List<Parameter>();
            parameters.Add(new Parameter("appid", this.appID));
            parameters.Add(new Parameter("muid", mediaUID));
            parameters = this.signRequest(parameters);

            HttpWebRequest request = this.combineRequest(url, parameters);

            String result = this.makeRequest(request);
        }

        /// <summary>
        /// 用户发布帖子、日志等信息时，可以把此信息分享到第三方
        /// </summary>
        /// <param name="mediaUserID"></param>
        /// <param name="content">分享显示的信息</param>
        /// <param name="url">查看信息的链接</param>
        /// <param name="uid">网站用户的唯一性标识ID</param>
        public void share(String mediaUserID, String content, String url, String uid)
        {
            String uri = Denglu.apiPath["share"];
            List<Parameter> parameters = new List<Parameter>();
            parameters.Add(new Parameter("appid", this.appID));
            parameters.Add(new Parameter("muid", mediaUserID));
            parameters.Add(new Parameter("uid", uid));
            parameters.Add(new Parameter("content", content));
            parameters.Add(new Parameter("url", url));
            parameters = this.signRequest(parameters);

            HttpWebRequest request = this.combineRequest(uri, parameters);

            String result = this.makeRequest(request);
        }

        /// <summary>
        /// 为HTTP请求加签名
        /// </summary>
        /// <param name="request"></param>
        protected List<Parameter> signRequest(List<Parameter> parameters)
        {
            //parameters.Sort(new ParameterComparer());

            String temp = "";
            foreach (var item in parameters)
            {
                temp += item.toParamString();
            }

            string sign = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(temp + this.apiKey, "MD5").ToLower();
            parameters.Add(new Parameter("sign", sign));

            return parameters;
        }

        protected HttpWebRequest combineRequest(String url, List<Parameter> parameters)
        {
            url += "?";
            foreach (var item in parameters)
            {
                if (!url.EndsWith("?"))
                {
                    url += "&";
                }
                url += item.toParamString();
            }

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = Verb.GET.ToString();
            return request;
        }

        /// <summary>
        /// 发送HTTP请求并获得响应
        /// </summary>
        /// <param name="request"></param>
        protected String makeRequest(HttpWebRequest request)
        {
            HttpWebResponse res = (HttpWebResponse)request.GetResponse();
            Stream response = res.GetResponseStream();
            StreamReader sr = new StreamReader(response);

            String result = sr.ReadToEnd();
            sr.Close();
            response.Close();

            return result;
        }

        /// <summary>
        /// 解析JSON字符串
        /// </summary>
        /// <param name="input"></param>
        protected Object parseJson(String input)
        {
            if (input.Trim().StartsWith("{"))
            {
                JObject result = JObject.Parse(input);
                if (result.Property("errorCode") != null)
                {
                    throw new DengluException(Int32.Parse(result.Property("errorCode").Value.ToString()), result.Property("errorDescription").Value.ToString());
                }
                return result;
            }
            else
            {
                JArray result = JArray.Parse(input);
                return result;
            }
        }

        /// <summary>
        /// 将json数据以DT解析返回(作废)
        /// </summary>
        /// <param name="input">json字符串</param>
        /// <returns></returns>
        public DataTable getDTByJson_s(String str)
        {
            str = str.Replace("{", "");
            str = str.Replace("}", "").Trim();

            String[] arr = str.Split(',');

            DataTable dt = new DataTable("strDT");//新建表
            foreach (String s in arr)
            {
                String s2 = s.Trim().Replace("\"", "");
                String[] arr2 = s2.Split(new char[] { ':', ' ' });
                dt.Columns.Add(arr2[0], typeof(String));//插入列
            }

            DataRow dr = dt.NewRow();
            foreach (String r in arr)
            {
                String s2 = r.Trim().Replace("\"", "");
                String[] arr2 = s2.Split(new char[] { ':', ' ' });

                String rStr = arr2[2];

                dr[arr2[0]] = rStr.Trim();
            }
            dt.Rows.Add(dr);//插入行

            return dt;
        }

        /// <summary>
        /// 将json数据以DT解析返回
        /// </summary>
        /// <param name="input">json字符串</param>
        /// <returns></returns>
        public DataTable getDTByJson(String str)
        {
            str = str.Replace("{", "");
            str = str.Replace("}", "").Trim();//如：{ 'mediaID': 13, 'createTime': '2011-11-07 12:12:19', 'friendsCount': 0, 'location': null, 'favouritesCount': 0, 'screenName': ' Universe', 'profileImageUrl': 'http://qzapp.qlogo.cn/qzapp/100225699/3757FD1A8129F3CD1953F96B259BD946/100', 'mediaUserID': 1006083, 'url': null, 'homepage': null, 'city': null, 'email': null, 'createdAt': '', 'verified': 0, 'description': null, 'name': ' Universe', 'province': null, 'domain': null, 'followersCount': 0, 'gender': 0, 'statusesCount': 0, 'personID': 747821 }

            String[] arr = str.Split(',');

            DataTable dt = new DataTable("strDT");//新建表
            foreach (String s in arr)
            {
                String s2 = s.Trim();
                String[] arr2 = s2.Split(new char[] { ':' });
                dt.Columns.Add(arr2[0].Replace("\"", ""), typeof(String));//插入列
            }

            DataRow dr = dt.NewRow();
            foreach (String r in arr)
            {
                String s2 = r.Trim();
                String[] arr2 = s2.Split(new char[] { ':' });

                String rStr = "";
                for (int v = 1; v < arr2.Length; v++)
                {
                    if (v == arr2.Length - 1)
                    { rStr += arr2[v].Trim(); }
                    else
                    { rStr += arr2[v].Trim() + ":"; }
                }               

                dr[arr2[0].Replace("\"", "")] = rStr.Trim().Replace("\"", "");
            }
            dt.Rows.Add(dr);//插入行

            return dt;
        }

    }//end Denglu
}
